#pragma once
#include <windows.h>
class CRemoteModuleBase;
class CRemoteProcess;

class CRemoteFunction
{
protected:
	FARPROC m_pfnLocal;
	CRemoteModuleBase* m_prm;
public:
	CRemoteFunction() : m_prm(NULL), m_pfnLocal(NULL)
	{
	}

	CRemoteFunction(CRemoteModuleBase* prm) : m_prm(prm), m_pfnLocal(NULL)
	{
	}

	BOOL Create(CRemoteModuleBase* pModule, LPCSTR pszName);
	DWORD Execute(LPVOID pParameter);
};

class CRemoteModuleBase
{
protected:
	HMODULE m_h;
	HMODULE m_hLocal;
	CRemoteProcess* m_prp;
public:
	HMODULE FindProcessModule(HANDLE hProcess, LPCTSTR pszBaseName);
	CRemoteModuleBase():m_prp(NULL), m_h(NULL), m_hLocal(NULL)
	{

	}

	CRemoteModuleBase(CRemoteProcess* prp) : m_prp(prp), m_h(NULL), m_hLocal(NULL)
	{
	}

	operator HMODULE()
	{
		return m_h;
	}

	HMODULE GetLocalHandle()
	{
		return m_hLocal;
	}

	CRemoteProcess* GetRemoteProcess()
	{
		return m_prp;
	}
};

class CRemoteModuleNL : public CRemoteModuleBase
{
public:
	CRemoteModuleNL()
	{
	}
	BOOL Create(CRemoteProcess* prp, LPCTSTR pszBaseName);
};

class CRemoteModule : public CRemoteModuleBase
{
public:
	CRemoteModule(CRemoteProcess* prp) : CRemoteModuleBase(prp)
	{
	}

	~CRemoteModule()
	{
		Destroy();
	}

	BOOL Create(LPCTSTR, HMODULE hLocal, HMODULE hRemote);
	void Destroy();
};

class CRemoteProcess
{
protected:
	HANDLE m_h;
	CRemoteModuleNL m_rmKernel;
	CRemoteFunction m_rfLoadLibrary;
	CRemoteFunction m_rfFreeLibrary;

	virtual HANDLE GetTargetProcess(HANDLE* ph, DWORD dwHandleCount);
public:
	BOOL FindProcess(LPCTSTR pszBaseName, DWORD dwDesiredAccess, HANDLE* pHandle, DWORD& dwHandleCount);

	CRemoteProcess() : m_h(NULL)
	{
	}

	~CRemoteProcess()
	{
		Destroy();
	}

	operator HANDLE()
	{
		if(m_h)
		{
			DWORD dwExitCode = 0;
			GetExitCodeProcess(m_h, &dwExitCode);
			if(dwExitCode != STILL_ACTIVE)
				Destroy();
		}

		return m_h;
	}

	BOOL Create(LPCTSTR pszBaseName, DWORD dwDesiredAccess);
	void Destroy()
	{
		if (m_h)
		{
			CloseHandle(m_h);
			m_h = NULL;
		}
	}

	HMODULE Load(LPCTSTR pszName);
	BOOL Free(HMODULE hmod);
};

class CRemoteProcessIE: public CRemoteProcess
{
protected:
	virtual HANDLE GetTargetProcess(HANDLE* ph, DWORD dwHandleCount);
};